package org.example.demo.dao;

import com.kfyang.manualgear.struct.Page;
import com.kfyang.manualgear.struct.PageResult;
import com.kfyang.manualgear.struct.PageResultImpl;
import com.kfyang.manualgear.util.ResultUtils;
import com.kfyang.manualgear.util.StringUtils;
import org.example.demo.entity.OrderEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Repository
public class OrderDaoExample {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    private final RowMapper<OrderEntity> o1Mapper = (rs, rowNum) -> {
        Integer id = rs.getInt("c1");
        String orderName = rs.getString("c2");
        Date orderDate = null;
        if (rs.getTimestamp("c3") != null) {
            orderDate = new java.util.Date(rs.getTimestamp("c3").getTime());
        }
        Integer customerId = rs.getInt("c4");
        return new OrderEntity(id, orderName, orderDate, customerId);
    };

    public PageResult<OrderEntity> queryPage(OrderEntity order, Page page) {
        // 查询结果
        StringBuilder querySql = new StringBuilder("select id c1, order_name c2, order_date c3, customer_id c4 ");

        querySql.append(" from `order` where 1=1");

        List<Object> parameters = new ArrayList<>();
        if (order.getOrderName() != null) {
            querySql.append(" and `order`.order_name = ?");
            parameters.add(order.getOrderName());
        }
        querySql.append(" or id = 2");

//        List<OrderEntity> queryResult = jdbcTemplate.query(querySql.toString(), o1Mapper, parameters.toArray());
//        Integer total = jdbcTemplate.queryForObject(countSql.toString(), (rs, rowNum) -> rs.getInt("c1"), parameters.toArray());
        return ResultUtils.pageResult(
            s -> jdbcTemplate.queryForObject(s, (rs, rowNum) -> rs.getInt("c1"), parameters.toArray()),
            s -> jdbcTemplate.query(s, o1Mapper, parameters.toArray()),
            querySql, page
        );
    }

    public OrderEntity queryForOne(OrderEntity order) {
        StringBuilder querySql = new StringBuilder("select id r1, order_name r2, order_date r3 from `order` where id = ?");
        List<Object> parameters = new ArrayList<>();
        parameters.add(order.getId());

        RowMapper<OrderEntity> rowMapper = (rs, rowNum) -> {
            OrderEntity orderEntity = new OrderEntity();
            orderEntity.setId(rs.getInt("r1"));
            orderEntity.setOrderName(rs.getString("r2"));
            return orderEntity;
        };
        return ResultUtils.originResult(s -> jdbcTemplate.queryForObject(s, rowMapper, parameters.toArray()),
            querySql);
//        return jdbcTemplate.queryForObject(sql.toString(), rowMapper, parameters.toArray());
    }

    public List<OrderEntity> queryForMany(OrderEntity order) {
        StringBuilder querySql = new StringBuilder("select id r1, order_name r2, order_date r3 from `order` where id = ?");
        List<Object> parameters = new ArrayList<>();
        parameters.add(order.getId());
        RowMapper<OrderEntity> rowMapper = (rs, rowNum) -> {
            OrderEntity orderEntity = new OrderEntity();
            orderEntity.setId(rs.getInt("r1"));
            orderEntity.setOrderName(rs.getString("r2"));
            return orderEntity;
        };
        return ResultUtils.listResult(s -> jdbcTemplate.query(s, rowMapper, parameters.toArray()),
            querySql);
//        return jdbcTemplate.query(sql.toString(), rowMapper, parameters.toArray());
    }

    public int update(OrderEntity order, String orderName) {
        StringBuilder sql = new StringBuilder("update `order` set customer_id = ? ");
        List<Object> parameters = new ArrayList<>();
        parameters.add(order.getCustomerId());

        if (!order.getOrderName().isEmpty()) {
            sql.append(" and orderName = ?");
            parameters.add(orderName);
        }

        sql.append("where orderDate not null");
        return jdbcTemplate.update(sql.toString(), parameters.toArray());
    }

    int update(List<Integer> list) {
        List<Object> parameters = new ArrayList<>();
        StringBuilder sql = new StringBuilder("update `order` set customer_id = 10 where id in "
            + StringUtils.inList(list.size()) + " and order_name = 'aa'");
        parameters.addAll(list);
        return jdbcTemplate.update(sql.toString(), parameters.toArray());
    }

    OrderEntity selectById(int id) {
        return jdbcTemplate.queryForObject("select id c1, create_time c2, update_time c3, order_name c4, order_date c5, customer_id c6 from `order` where id = ? and is_deleted = 0",
            (rs, rowNum) -> {
                OrderEntity orderEntity = new OrderEntity();
                orderEntity.setId(rs.getInt("c1"));
                if (rs.getTimestamp("c2") != null) {
                    orderEntity.setCreateTime(new java.util.Date(rs.getTimestamp("c2").getTime()));
                }
                if (rs.getTimestamp("c3") != null) {
                    orderEntity.setUpdateTime(new java.util.Date(rs.getTimestamp("c3").getTime()));
                }
                orderEntity.setOrderName(rs.getString("c4"));
                orderEntity.setOrderDate(new java.util.Date(rs.getTimestamp("c5").getTime()));
                orderEntity.setCustomerId(rs.getInt("c6"));
                return orderEntity;
            }, id);
    }

    List<OrderEntity> selectAll() {
        return jdbcTemplate.query("select id c1, create_time c2, update_time c3, order_name c4, order_date c5, customer_id c6 from `order` where is_deleted = 0",
            (rs, rowNum) -> {
                OrderEntity orderEntity = new OrderEntity();
                orderEntity.setId(rs.getInt("c1"));
                if (rs.getTimestamp("c2") != null) {
                    orderEntity.setCreateTime(new java.util.Date(rs.getTimestamp("c2").getTime()));
                }
                if (rs.getTimestamp("c3") != null) {
                    orderEntity.setUpdateTime(new java.util.Date(rs.getTimestamp("c3").getTime()));
                }
                orderEntity.setOrderName(rs.getString("c4"));
                orderEntity.setOrderDate(new java.util.Date(rs.getTimestamp("c5").getTime()));
                orderEntity.setCustomerId(rs.getInt("c6"));
                return orderEntity;
            });
    }

    int insert(OrderEntity entity) {
        Object[] parameters = {new Date(), new Date(),
            entity.getOrderName(), entity.getOrderDate(), entity.getCustomerId()};
        return jdbcTemplate.update("insert into `order`(create_time, update_time, order_name, order_date, customer_id) values (?,?,?,?,?)", parameters);
    }

    int insertAll(List<OrderEntity> entityList) {
        List<Object> parameters = new ArrayList<>();
        for (OrderEntity entity : entityList) {
            parameters.add(new Date());
            parameters.add(new Date());
            parameters.add(entity.getOrderName());
            parameters.add(entity.getOrderDate());
            parameters.add(entity.getCustomerId());
        }
        String sql = "insert into `order`(create_time, update_time, order_name, order_date, customer_id) values " +
            "(?,?,?,?,?),".repeat(Math.max(0, entityList.size() - 1)) +
            "(?,?,?,?,?)";
        return jdbcTemplate.update(sql, parameters.toArray());
    }

    int update(OrderEntity entity) {
        Object[] parameters = {new Date(),
            entity.getOrderName(), entity.getOrderDate(), entity.getCustomerId(), entity.getId()};
//        return jdbcTemplate.update("update `order` set create_time = ?, update_time = ?, order_name = ?, " +
//            "order_date = ?, customer_id = ? where id = ?", parameters);
        return jdbcTemplate.update("update `order` set update_time = ?, order_name = ?, " +
            "order_date = ?, customer_id = ? where id = ? and is_deleted = 1", parameters);
    }

    @Transactional
    public int deleteById(int id) {
//        return jdbcTemplate.update("delete from `order` where id = ?", id);
        return jdbcTemplate.update("update `order` set is_deleted = 1 and update_time = ? where id = ?", new Date(), id);

//        throw new RuntimeException();
//        return count;
    }

    int deleteByIds(List<Integer> ids) {
//        return jdbcTemplate.update("delete from `order` where id in " + StringUtils.inList(ids.size()), ids.toArray());
        return jdbcTemplate.update("update `order` set is_deleted = 1 and update_time = ? where id in " + StringUtils.inList(ids.size()), new Date(), ids.toArray());
    }
}
